package com.socialsoftware.util;

import android.util.Base64;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * 用于处理JWT令牌的工具类
 */
public class JwtTokenUtil {
    private static final String TAG = "JwtTokenUtil";
    
    /**
     * 从JWT令牌解析claims部分
     * @param token JWT令牌字符串
     * @return JSON对象，包含令牌中的claims信息
     */
    public static JSONObject parseJwtClaims(String token) {
        if (token == null || token.isEmpty()) {
            Log.e(TAG, "令牌为空");
            return null;
        }
        
        try {
            // JWT令牌格式为：header.payload.signature
            String[] parts = token.split("\\.");
            if (parts.length != 3) {
                Log.e(TAG, "无效的JWT令牌格式");
                return null;
            }
            
            // 确保payload部分不为空
            String payload = parts[1];
            if (payload == null || payload.isEmpty()) {
                Log.e(TAG, "JWT令牌payload部分为空");
                return null;
            }
            
            // 处理Base64解码中的填充问题
            // 标准Base64编码长度必须是4的倍数，JWT可能会省略填充字符=
            while (payload.length() % 4 != 0) {
                payload += "=";
            }
            
            // 解码payload部分（Base64URL编码的JSON）
            byte[] decodedBytes;
            try {
                decodedBytes = Base64.decode(payload, Base64.URL_SAFE);
                if (decodedBytes == null || decodedBytes.length == 0) {
                    Log.e(TAG, "JWT令牌payload解码失败");
                    return null;
                }
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "JWT令牌payload解码出错: " + e.getMessage());
                return null;
            }
            
            String decodedPayload = new String(decodedBytes, "UTF-8");
            
            // 解析为JSON对象
            return new JSONObject(decodedPayload);
            
        } catch (UnsupportedEncodingException | JSONException e) {
            Log.e(TAG, "解析JWT令牌失败: " + e.getMessage(), e);
            return null;
        } catch (Exception e) {
            // 捕获所有其他异常，以确保此方法不会导致崩溃
            Log.e(TAG, "解析JWT令牌时发生未知错误: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 检查令牌是否已过期
     * @param token JWT令牌字符串
     * @return 如果令牌已过期或无效，则返回true
     */
    public static boolean isTokenExpired(String token) {
        if (token == null || token.isEmpty()) {
            return true;
        }
        
        try {
            JSONObject claims = parseJwtClaims(token);
            if (claims == null) {
                return true;
            }
            
            // 检查是否存在exp声明
            if (!claims.has("exp")) {
                Log.e(TAG, "JWT令牌缺少过期时间声明");
                return true;
            }
            
            // 获取过期时间（exp声明是Unix时间戳，单位为秒）
            long expirationTime = claims.getLong("exp") * 1000; // 转换为毫秒
            Date expirationDate = new Date(expirationTime);
            
            // 与当前时间比较
            return expirationDate.before(new Date());
            
        } catch (JSONException e) {
            Log.e(TAG, "获取令牌过期时间失败: " + e.getMessage(), e);
            return true;
        } catch (Exception e) {
            // 捕获所有其他异常，以确保此方法不会导致崩溃
            Log.e(TAG, "检查令牌过期时发生未知错误: " + e.getMessage(), e);
            return true;
        }
    }
    
    /**
     * 从令牌中获取用户名
     * @param token JWT令牌字符串
     * @return 用户名，如果令牌无效则返回null
     */
    public static String getUsernameFromToken(String token) {
        if (token == null || token.isEmpty()) {
            return null;
        }
        
        try {
            JSONObject claims = parseJwtClaims(token);
            if (claims == null) {
                return null;
            }
            
            // Spring Security JWT通常使用"sub"（subject）声明存储用户名
            if (claims.has("sub")) {
                return claims.getString("sub");
            } else {
                Log.w(TAG, "JWT令牌不包含subject声明");
                return null;
            }
            
        } catch (JSONException e) {
            Log.e(TAG, "从令牌获取用户名失败: " + e.getMessage(), e);
            return null;
        } catch (Exception e) {
            // 捕获所有其他异常，以确保此方法不会导致崩溃
            Log.e(TAG, "获取用户名时发生未知错误: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 从令牌中获取用户角色
     * @param token JWT令牌字符串
     * @return 用户角色，如果令牌无效或不包含角色信息则返回null
     */
    public static String getUserRoleFromToken(String token) {
        if (token == null || token.isEmpty()) {
            return null;
        }
        
        try {
            JSONObject claims = parseJwtClaims(token);
            if (claims == null) {
                return null;
            }
            
            // 根据后端实现，角色信息可能存储在不同的声明中
            // 常见的有"role"、"authorities"或自定义字段
            if (claims.has("role")) {
                return claims.getString("role");
            } else if (claims.has("authorities")) {
                return claims.getString("authorities");
            } else if (claims.has("scope")) {
                return claims.getString("scope");
            }
            
            return null;
            
        } catch (JSONException e) {
            Log.e(TAG, "从令牌获取用户角色失败: " + e.getMessage(), e);
            return null;
        } catch (Exception e) {
            // 捕获所有其他异常，以确保此方法不会导致崩溃
            Log.e(TAG, "获取用户角色时发生未知错误: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 获取令牌过期时间（距离现在的毫秒数）
     * @param token JWT令牌字符串
     * @return 过期前的剩余毫秒数，如果令牌已过期或无效则返回-1
     */
    public static long getTokenExpirationTime(String token) {
        if (token == null || token.isEmpty()) {
            return -1;
        }
        
        try {
            JSONObject claims = parseJwtClaims(token);
            if (claims == null) {
                return -1;
            }
            
            // 检查是否存在exp声明
            if (!claims.has("exp")) {
                Log.e(TAG, "JWT令牌缺少过期时间声明");
                return -1;
            }
            
            long expirationTime = claims.getLong("exp") * 1000; // 转换为毫秒
            long currentTime = System.currentTimeMillis();
            
            long timeRemaining = expirationTime - currentTime;
            return timeRemaining > 0 ? timeRemaining : -1;
            
        } catch (JSONException e) {
            Log.e(TAG, "获取令牌过期时间失败: " + e.getMessage(), e);
            return -1;
        } catch (Exception e) {
            // 捕获所有其他异常，以确保此方法不会导致崩溃
            Log.e(TAG, "获取令牌过期时间时发生未知错误: " + e.getMessage(), e);
            return -1;
        }
    }
    
    /**
     * 验证令牌是否有效（结构正确，未过期）
     * @param token JWT令牌字符串
     * @return 如果令牌有效则返回true
     */
    public static boolean validateToken(String token) {
        if (token == null || token.isEmpty()) {
            return false;
        }
        
        // 1. 检查格式
        String[] parts = token.split("\\.");
        if (parts.length != 3) {
            Log.e(TAG, "无效的JWT令牌格式");
            return false;
        }
        
        // 2. 检查是否能解析
        JSONObject claims = parseJwtClaims(token);
        if (claims == null) {
            return false;
        }
        
        // 3. 检查是否过期
        return !isTokenExpired(token);
    }
} 